package org.mobilesynergies.android.epic.service.core;

import org.mobilesynergies.android.epic.service.EpicService;

import org.mobilesynergies.android.epic.service.interfaces.IEpicServiceApplicationInterface;
import org.mobilesynergies.android.epic.service.interfaces.IApplicationStatusChangeCallback;
import org.mobilesynergies.android.epic.service.interfaces.IRemoteCommandCallback;

import org.mobilesynergies.android.epic.service.interfaces.IIncomingMessageCallback;
import org.mobilesynergies.android.epic.service.interfaces.IServiceStatusChangeCallback;

import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;


/**
 * This class implements the application interface. It is used to let 3rd party apps connect to the EPIC service and to use it as a message oriented middleware.    
 * All functions run in the thread of the caller and block it.
 * Therefore the functions will call handlers in the EpicService thread. 
 */
public class ApplicationInterface extends IEpicServiceApplicationInterface.Stub {
	
	private static String CLASS_TAG = ApplicationInterface.class.getSimpleName(); 
	
	
	private EpicService mEpicServiceContext = null;

	public ApplicationInterface(EpicService context)
	{
		mEpicServiceContext = context;
	}
	
	@Override
	public int getVersion() throws RemoteException {
		return EpicService.EPIC_SERVICE_VERSION_NUMBER;
	}

	@Override
	public String bindApplication(String applicationKey,
			String applicationPassword, String applicationManifest)
	throws RemoteException {

		// TODO check the applicationKey and the applicationPassword with the Epic server

		ApplicationSession appSession = new ApplicationSession(applicationManifest);

		//TODO generate appropriate sessionKey (using encryption to prevent a man in the middle attack between epic service and application)
		String sessionKey = applicationKey;
		mEpicServiceContext.addSession(applicationKey, appSession);
		
		return sessionKey;
	}
	
	@Override
	public void registerApplicationStatusChangeCallback(String sessionKey,
			IApplicationStatusChangeCallback callback)
	throws RemoteException {
		// TODO: check validity of sessionKey
		mEpicServiceContext.registerApplicationStatusChangeCallback(sessionKey, callback);
	}

	@Override
	public void registerServiceStatusChangeCallback(
			IServiceStatusChangeCallback callback) throws RemoteException {
		mEpicServiceContext.registerServiceStatusChangeCallback(callback);
		
	}

	@Override
	public String getSessionToken(String sessionKey,
			String applicationNodeId) throws RemoteException {

		ApplicationSession session = mEpicServiceContext.getApplicationSessions(sessionKey);
		if(session==null) {
			Log.w(CLASS_TAG, "Unknown application tried to get a sessionToken for an applicationNode.");
			return null;
		}

		if( ! session.mApplicationNodes.contains(applicationNodeId) )
		{
			Log.w(CLASS_TAG, "Unknown application node. The applicationNodeId needs to be declared in the epic-manifest file.");
			return null;
		}

		//TODO generate unique sessionToken - not only unique for the application but for all applications
		String sessionToken = sessionKey+applicationNodeId;
		return sessionToken;
	}

	@Override
	public void listenForMessages(String sessionToken, 
			IIncomingMessageCallback messageCallback, 
			String publisherId)
	throws RemoteException {
		// TODO: check validity of sessionToken
		mEpicServiceContext.registerSubscriberCallback(sessionToken, messageCallback);
	}
	
	@Override
	public Bundle requestResponse(String sessionToken, Bundle object)
	throws RemoteException {
		// TODO: check validity of sessionToken
		mEpicServiceContext.requestResponse(sessionToken, object);
		return null;
	}

	@Override
	public void sendMessage(String sessionToken, Bundle object)
	throws RemoteException {
		// TODO: check validity of sessionToken
		mEpicServiceContext.sendMessage(sessionToken, object);
	}

	@Override
	public void stopListening(String sessionToken) throws RemoteException {
		// TODO: check validity of sessionToken
		mEpicServiceContext.removeSubscriberCallback(sessionToken);
	}

	@Override
	public void registerPublicCommand(String sessionToken, IRemoteCommandCallback cb) throws RemoteException {
		
	}

	


	






}